﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

public class CtrBooking
{
    private static object obj = new object();
    private DBBooking dbb = new DBBooking();
    private DBTicket dbt = new DBTicket();
    private CtrCustomer ctrc = new CtrCustomer();

    public Booking Read(int id)
    {
        Booking bo = dbb.Read(id);
        foreach (Ticket tic in dbt.ReadFromBookingId(bo.Id))
        {
            bo.TicketList(tic);
        }

        return bo;
    }
    public List<Booking> Read(Customer customer)
    {
        List<Booking> books = dbb.Read(customer);
        foreach (Booking bo in books)
        {
            foreach (Ticket tic in dbt.ReadFromBookingId(bo.Id))
            {
                bo.TicketList(tic);
            }
        }
        return books;
    }
    public int Insert(Booking booking)
    {
        return dbb.Insert(booking);
    }
    public int Update(Booking booking)
    {
        return dbb.Update(booking);
    }
    public int BookingMaxID()
    {
        return dbb.BookingMaxID();
    }

    public void CheckBooking()
    {
        List<Booking> timeBooking = dbb.FindBookingByTime();
        List<Ticket> tic = new List<Ticket>();
        foreach (Booking item in timeBooking)
        {
            item.Status = 3;

            Update(item);

            tic = dbt.ReadFromBookingId(item.Id);

            foreach (Ticket Titem in tic)
            {
                Titem.Invalid = true;
                dbt.Update(Titem);
            }

        }
    }
 
    public Booking BookingObject(int id, double totalprice, int status, string customerphone)
    {
        return new Booking(id, totalprice, status, customerphone);
    }

    /// <summary>
    /// This method created a new booking, based on a list of tickets and a customer.
    /// The method will not leave any bookings in the database if the tickets cannot be inserted.
    /// </summary>
    /// <returns>The resulting booking. Will be null if no booking could be made!</returns>
    public Booking CreateBooking(List<Ticket> tickets, Customer customer, int status)
    {
        //We don't want anyone else to insert tickets in the middle of this operation.
        Monitor.Enter(obj);
        bool exists = false;
        Booking book = new Booking(status, customer.PhoneNo);
        try
        {
            //Make sure there's a customer with the right phonenumber in the database.
            if (ctrc.Read(customer.PhoneNo).Count < 1)
            {
                ctrc.Insert(customer);
            }
            book.Id = dbb.Insert(book);
            foreach (var ticket in tickets)
            {
                List<Ticket> checkList = dbt.Read(ticket);
                if (ticket.ShowTime.CinemaRoom.Id != ticket.Seat.CinemaRoom || (checkList.Count > 0 && checkList.Any(x => !x.Invalid)))
                {
                    exists = true;
                    break;
                }
            }
            //Make sure to actually add the tickets if they do not exist.
            if (!exists)
            {
                foreach (var ticket in tickets)
                {
                    ticket.Booking = book;
                    dbt.Insert(ticket);
                }
            }
            else
            {
                dbb.Delete(book.Id);
                book = null;
            }
        }
        finally 
        {
            Monitor.Exit(obj);
        }
        return book;
    }

    public Booking CreateBookingFromSeats(ShowTime showTime, List<Seat> seats, Customer customer)
    {
        List<Ticket> tickets = new List<Ticket>();
        foreach (var seat in seats)
        {
            tickets.Add(new Ticket(seat.Price + showTime.Price + showTime.Movie.Price, showTime, seat));
        }
        return CreateBooking(tickets, customer, 2);
    }
}

